/**
 * @file activity.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_watch.h"

#if USE_LV_WATCH_ACTIVITY!= 0

/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
static lv_obj_t * activity_create(lv_obj_t * activity_obj);
static void activity_prepare_destory(lv_obj_t * activity_obj);
static lv_activity_ext_t * activity_get_ext(void);
static lv_obj_t * activity_tileview_add_tile(lv_obj_t * tileview, uint16_t id);
static void tile_summary_create(uint8_t id);
static void tile_calorie_create(uint8_t id);
static void tile_distribution_create(uint8_t id);
static void tile_steps_create(uint8_t id);
static void tile_strength_create(uint8_t id);
static void tile_hours_create(uint8_t id);
static void tile_common_create(lv_obj_t * cont, tile_common_desc_t * desc);
static void activity_update_anim(lv_obj_t * obj);
static void activity_update_anim_cb(lv_anim_t * anim);
static void tile_summary_add_element(lv_obj_t * cont);

/**********************
 *  STATIC VARIABLES
 **********************/
static const watchLangTxtId_t week_txt_id[] = {
    WATCH_TEXT_ID_CALENDAR_SUNDAY,
    WATCH_TEXT_ID_CALENDAR_MONDAY,
    WATCH_TEXT_ID_CALENDAR_TUESDAY,
    WATCH_TEXT_ID_CALENDAR_WEDNESDAY,
    WATCH_TEXT_ID_CALENDAR_THURSDAY,
    WATCH_TEXT_ID_CALENDAR_FRIDAY,
    WATCH_TEXT_ID_CALENDAR_SATURDAY,
};

static activity_tile_create_func tile_create_func[ACTIVITY_TILE_COUNT] = {
    tile_summary_create,
    tile_calorie_create,
    tile_distribution_create,
    tile_steps_create,
    tile_strength_create,
    tile_hours_create,
};

static app_adaptor_activity_info_t activity_info;

/**********************
 *      MACROS
 **********************/
#define ACTIVITY_OCLOCK_TEXT_CNT  4

/**********************
 *   GLOBAL FUNCTIONS
***********************/
void activity_create_event_cb(lv_obj_t * btn, lv_event_t e)
{
    (void)btn;

    if(LV_EVENT_CLICKED == e) {
        activity_create(NULL);
    }
}

#if USE_LV_WATCH_LAUNCHER2 != 0
void sport_create_tab(lv_obj_t * par)
{
    app_adaptor_get_activity_info_req(&activity_info);
    tile_summary_add_element(par);
    activity_update_anim(par);
}
#endif

/**********************
 *   STATIC FUNCTIONS
 **********************/
static lv_obj_t * activity_create(lv_obj_t * activity_obj)
{
    /* activity obj */
    if(NULL == activity_obj) {
        lv_watch_activity_ext_t activity_ext;
        memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
        activity_ext.actId = ACT_ID_ACTIVITY;
        activity_ext.create = activity_create;
        activity_ext.prepare_destory = activity_prepare_destory;
        activity_obj = lv_watch_creat_activity_obj(&activity_ext);
    } else {
        lv_obj_clean(activity_obj);
    }

    /* watch obj */
    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    lv_activity_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(lv_activity_ext_t));
    LV_ASSERT_MEM(ext);
    ext->tile_summary_cont = NULL;
    ext->tile_calorie_cont = NULL;
    ext->tile_distribution_cont = NULL;
    ext->tile_steps_cont = NULL;
    ext->tile_strength_cont = NULL;
    ext->tile_hours_cont = NULL;

    /* get activity info*/
    app_adaptor_get_activity_info_req(&activity_info);

    /* get rtc time */
    Hal_Rtc_Gettime(&ext->rtc_time);

    /* tileview */
    static lv_point_t valid_pos[] = {{0,0}, {0, 1}, {0,2}, {0,3}, {0,4}, {0,5}};
    lv_obj_t * tileview = lv_tileview_create(obj, NULL);
    ext->tileview = tileview;
    lv_tileview_set_valid_positions(tileview, valid_pos, 6);
    lv_tileview_set_edge_flash(tileview, true);
    lv_page_set_scrollbar_mode(tileview, LV_SCROLLBAR_MODE_OFF);
    lv_watch_obj_add_element(tileview);
    lv_watch_obj_add_element(lv_page_get_scrl(tileview));

    for(uint8_t i=0; i<ACTIVITY_TILE_COUNT; i++) {
        tile_create_func[i](i);
    }

    //anim
    activity_update_anim(ext->tileview);

    return obj;
}

static void activity_prepare_destory(lv_obj_t * activity_obj)
{
    lv_watch_png_cache_all_free();
}

static lv_activity_ext_t * activity_get_ext(void)
{
    lv_activity_ext_t  * ext = NULL;

    lv_obj_t * watch_obj = NULL;
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(ACT_ID_ACTIVITY);
    if(activity_obj) {
        lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &watch_obj);

        if(watch_obj) {
            ext = lv_obj_get_ext_attr(watch_obj);
        }
    }

    return ext;
}

static lv_obj_t * activity_tileview_add_tile(lv_obj_t * tileview, uint16_t id)
{
    lv_tileview_ext_t * ext = lv_obj_get_ext_attr(tileview);
    lv_obj_t * cont = lv_cont_create(tileview, NULL);
    lv_obj_add_style(cont, LV_CONT_PART_MAIN, &lv_style_transp_tight);
    lv_obj_set_size(cont, LV_HOR_RES, LV_VER_RES);
    lv_obj_set_y(cont, LV_VER_RES * ext->valid_pos[id].y);
    lv_obj_set_click(cont, false);

    lv_tileview_add_element(tileview, cont);
    lv_watch_obj_add_element(cont);

    return cont;
}

static void tile_summary_add_element(lv_obj_t * cont)
{
    uint32_t value_steps_today = activity_info.steps_today; //steps
    uint32_t value_steps_goal = activity_info.steps_goal;
    uint32_t value_strength_today = activity_info.high_strength_today;  //mins
    uint32_t value_strength_goal = activity_info.high_strength_goal;
    uint32_t value_hours_today = activity_info.active_hours_today;  //hours
    uint32_t value_hours_goal = activity_info.active_hours_goal;
    uint16_t angle_end;
    uint16_t line_width = 10*LV_HOR_RES/240;
    lv_obj_t * tileview = lv_obj_get_parent(lv_obj_get_parent(cont));
    #if USE_LV_WATCH_LAUNCHER2 != 0
    if(lv_watch_get_activity_obj(ACT_ID_ACTIVITY) == NULL) {
        tileview = launcher_get_tileview_obj();
    }
    #endif

    //arc
    lv_obj_t * arc_steps = lv_arc_create(cont, NULL);
    lv_arc_set_bg_angles(arc_steps, 135, 405);
    if(value_steps_today <= value_steps_goal) {
        angle_end = 135 + 270*value_steps_today/value_steps_goal;
    } else {
        angle_end = 405;
    }
    lv_arc_set_angles(arc_steps, 135, angle_end);
    lv_obj_set_size(arc_steps, LV_HOR_RES-10, LV_VER_RES-10);
    lv_obj_align(arc_steps, NULL, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_style_local_line_color(arc_steps, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
    lv_obj_set_style_local_line_width(arc_steps, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, line_width);
    lv_obj_set_style_local_line_color(arc_steps, LV_ARC_PART_BG, LV_STATE_DEFAULT, LV_COLOR_GRAY);
    lv_obj_set_style_local_line_width(arc_steps, LV_ARC_PART_BG, LV_STATE_DEFAULT, line_width);
    lv_obj_set_style_local_line_opa(arc_steps, LV_ARC_PART_BG, LV_STATE_DEFAULT, LV_OPA_50);
    lv_obj_set_style_local_bg_opa(arc_steps, LV_ARC_PART_BG, LV_STATE_DEFAULT, LV_OPA_0);
    lv_tileview_add_element(tileview, arc_steps);

    lv_obj_t * arc_strength = lv_arc_create(cont, arc_steps);
    if(value_strength_today <= value_strength_goal) {
        angle_end = 135 + 270*value_strength_today/value_strength_goal;
    } else {
        angle_end = 405;
    }
    lv_arc_set_angles(arc_strength, 135, angle_end);
    lv_obj_set_size(arc_strength, lv_obj_get_width(arc_steps) - 2*(line_width+3), lv_obj_get_height(arc_steps) - 2*(line_width+3));
    lv_obj_align(arc_strength, NULL, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_style_local_line_color(arc_strength, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_ORANGE);
    lv_tileview_add_element(tileview, arc_strength);

    lv_obj_t * arc_hours = lv_arc_create(cont, arc_steps);
    if(value_hours_today <= value_hours_goal) {
        angle_end = 135 + 270*value_hours_today/value_hours_goal;
    } else {
        angle_end = 405;
    }
    lv_arc_set_angles(arc_hours, 135, angle_end);
    lv_obj_set_size(arc_hours, lv_obj_get_width(arc_strength) - 2*(line_width+3), lv_obj_get_height(arc_strength) - 2*(line_width+3));
    lv_obj_align(arc_hours, NULL, LV_ALIGN_CENTER, 0, 0);
    lv_obj_set_style_local_line_color(arc_hours, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_LIME);
    lv_tileview_add_element(tileview, arc_hours);

    //btn
    lv_obj_t * btn_strength = lv_btn_create(cont, NULL);
    lv_obj_add_style(btn_strength, LV_BTN_PART_MAIN, &lv_style_transp_fit);
    lv_btn_set_fit2(btn_strength, LV_FIT_TIGHT, LV_FIT_NONE);
    lv_btn_set_layout(btn_strength, LV_LAYOUT_ROW_MID);
    lv_obj_set_click(btn_strength, false);
    lv_obj_t * img_strength = lv_img_create(btn_strength, NULL);
    lv_img_set_src(img_strength, ICON_ACTIVITY_STRENGTH);
    lv_obj_t * label_strength = lv_label_create(btn_strength, NULL);
    char str[ACTIVITY_STR_LENGTH];
    memset(str, 0, ACTIVITY_STR_LENGTH);
    snprintf(str, ACTIVITY_STR_LENGTH, "%d/%d", value_strength_today, value_strength_goal);
    lv_label_set_text(label_strength, str);
    lv_obj_add_style(label_strength, LV_LABEL_PART_MAIN, &lv_watch_font30);
    lv_obj_align(btn_strength, NULL, LV_ALIGN_CENTER, 0, 0);
    lv_tileview_add_element(tileview, btn_strength);

    lv_obj_t * btn_steps = lv_btn_create(cont, btn_strength);
    lv_obj_align(btn_steps, btn_strength, LV_ALIGN_OUT_TOP_LEFT, 0, -10*LV_VER_RES/240);
    lv_obj_t * img_steps = lv_img_create(btn_steps, img_strength);
    lv_img_set_src(img_steps, ICON_ACTIVITY_STEPS);
    lv_obj_t * label_steps = lv_label_create(btn_steps, label_strength);
    memset(str, 0, ACTIVITY_STR_LENGTH);
    snprintf(str, ACTIVITY_STR_LENGTH, "%d", value_steps_today);
    lv_label_set_text(label_steps , str);
    lv_tileview_add_element(tileview, btn_steps);

    lv_obj_t * btn_hours = lv_btn_create(cont, btn_strength);
    lv_obj_align(btn_hours , btn_strength, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10*LV_VER_RES/240);
    lv_obj_t * img_hours = lv_img_create(btn_hours, img_strength);
    lv_img_set_src(img_hours, ICON_ACTIVITY_HOURS);
    lv_obj_t * label_hours = lv_label_create(btn_hours, label_strength);
    memset(str, 0, ACTIVITY_STR_LENGTH);
    snprintf(str, ACTIVITY_STR_LENGTH, "%d/%d", value_hours_today, value_hours_goal);
    lv_label_set_text(label_hours , str);
    lv_tileview_add_element(tileview, btn_hours);

    lv_obj_set_click(arc_steps, false);
    lv_obj_set_click(arc_strength, false);
    lv_obj_set_click(arc_hours, false);
    lv_obj_set_click(btn_strength, false);
    lv_obj_set_click(btn_steps, false);
    lv_obj_set_click(btn_hours, false);
}

static void tile_summary_create(uint8_t id)
{  
    lv_activity_ext_t * ext = activity_get_ext();
    lv_obj_t * tileview = ext->tileview;

    if(NULL == ext->tile_summary_cont) {
        ext->tile_summary_cont = activity_tileview_add_tile(tileview, id);
    } else {
        lv_obj_clean(ext->tile_summary_cont);
    }
    lv_obj_t * cont = ext->tile_summary_cont;
    tile_summary_add_element(cont);

    //label - symbol up
    lv_obj_t * label_up = lv_label_create(cont, NULL);
    lv_label_set_text(label_up, LV_SYMBOL_UP);
    lv_obj_set_style_local_text_font(label_up, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_THEME_WATCH_NIGHT_SYMBOL_NORMAL);
    lv_obj_align(label_up, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -20*LV_VER_RES/240);
    lv_tileview_add_element(tileview, label_up);
    lv_watch_obj_add_element(label_up);
}

static void tile_calorie_create(uint8_t id)
{
    double value_calorie = activity_info.calorie;
    double value_distance = activity_info.distance;
    double value_stairs = activity_info.stairs;

    lv_activity_ext_t * ext = activity_get_ext();
    lv_obj_t * tileview = ext->tileview;

    if(NULL == ext->tile_calorie_cont) {
        ext->tile_calorie_cont = activity_tileview_add_tile(tileview, id);
    } else {
        lv_obj_clean(ext->tile_calorie_cont);
    }
    lv_obj_t * cont = ext->tile_calorie_cont;

    //distance
    lv_obj_t * btn_distance = lv_btn_create(cont, NULL);
    lv_obj_add_style(btn_distance, LV_BTN_PART_MAIN, &lv_style_transp_fit);
    lv_btn_set_fit2(btn_distance, LV_FIT_TIGHT, LV_FIT_TIGHT);
    lv_btn_set_layout(btn_distance, LV_LAYOUT_ROW_MID);
    lv_obj_set_click(btn_distance, false);

    lv_obj_t * img_distance = lv_img_create(btn_distance, NULL);
    lv_img_set_src(img_distance, ICON_ACTIVITY_DISTANCE);

    lv_obj_t * cont_distance = lv_cont_create(btn_distance, NULL);
    lv_obj_add_style(cont_distance, LV_OBJ_PART_MAIN, &lv_style_transp_fit);
    lv_obj_set_click(cont_distance, false);
    lv_cont_set_fit2(cont_distance, LV_FIT_TIGHT, LV_FIT_TIGHT);
    if(LV_BIDI_DIR_RTL == lv_obj_get_base_dir(cont)) {
        lv_cont_set_layout(cont_distance, LV_LAYOUT_COLUMN_RIGHT);
    } else {
        lv_cont_set_layout(cont_distance, LV_LAYOUT_COLUMN_LEFT);
    }

    lv_obj_t * label_distance = lv_label_create(cont_distance, NULL);
    lv_label_set_text_id(label_distance, WATCH_TEXT_ID_DISTANCE);
    lv_obj_add_style(label_distance, LV_LABEL_PART_MAIN, &lv_watch_font20_gray);

    lv_obj_t * label_distance_v = lv_label_create(cont_distance, NULL);
    char str[ACTIVITY_STR_LENGTH];
    memset(str, 0, ACTIVITY_STR_LENGTH);
    snprintf(str, ACTIVITY_STR_LENGTH, "%.2f", value_distance);
    strcat(str, " ");
    strcat(str, lv_lang_get_text(WATCH_TEXT_ID_KMETERS));
    lv_label_set_text(label_distance_v, str);
    lv_obj_add_style(label_distance_v, LV_LABEL_PART_MAIN, &lv_watch_font20);

    lv_obj_align(btn_distance, NULL, LV_ALIGN_CENTER, 0, 0);

    //calorie
    lv_obj_t * btn_calorie = lv_btn_create(cont, btn_distance);
    lv_obj_align(btn_calorie, btn_distance, LV_ALIGN_OUT_TOP_LEFT, 0, -10*LV_VER_RES/240);

    lv_obj_t * img_calorie = lv_img_create(btn_calorie, img_distance);
    lv_img_set_src(img_calorie, ICON_ACTIVITY_CALORIE);

    lv_obj_t * cont_calorie = lv_cont_create(btn_calorie, cont_distance);
    lv_obj_t * label_calorie = lv_label_create(cont_calorie, label_distance);
    lv_label_set_text_id(label_calorie, WATCH_TEXT_ID_CALORIE);

    lv_obj_t * label_calorie_v = lv_label_create(cont_calorie, label_distance_v);
    memset(str, 0, ACTIVITY_STR_LENGTH);
    snprintf(str, ACTIVITY_STR_LENGTH, "%.0f", value_calorie);
    strcat(str, " ");
    strcat(str, lv_lang_get_text(WATCH_TEXT_ID_KCALORIES));
    lv_label_set_text(label_calorie_v, str);

    //climb stairs
    lv_obj_t * btn_stairs = lv_btn_create(cont, btn_distance);
    lv_obj_align(btn_stairs, btn_distance, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 10*LV_VER_RES/240);

    lv_obj_t * img_stairs = lv_img_create(btn_stairs, img_distance);
    lv_img_set_src(img_stairs, ICON_ACTIVITY_CLIMB_STAIRS);

    lv_obj_t * cont_stairs = lv_cont_create(btn_stairs, cont_distance);
    lv_obj_t * label_stairs = lv_label_create(cont_stairs, label_distance);
    lv_label_set_text_id(label_stairs, WATCH_TEXT_ID_CLIMB_STAIRS);

    lv_obj_t * label_stairs_v = lv_label_create(cont_stairs, label_distance_v);
    memset(str, 0, ACTIVITY_STR_LENGTH);
    snprintf(str, ACTIVITY_STR_LENGTH, "%.1f", value_stairs);
    strcat(str, " ");
    strcat(str, lv_lang_get_text(WATCH_TEXT_ID_METERS));
    lv_label_set_text(label_stairs_v, str);
}

static void tile_distribution_create(uint8_t id)
{
    uint8_t active[ACTIVITY_OCLOCK_CNT];
    uint8_t active_cnt = 0;
    uint8_t inactive_cnt = 0;
    uint8_t active_percent = 0;
    uint8_t inactive_percent = 0;
    static uint8_t s_active[ACTIVITY_OCLOCK_CNT] = {0};
    static uint8_t tm_hour = 0;

    for(uint8_t i = 0; i < ACTIVITY_OCLOCK_CNT; i++) {
        active[i] = activity_info.active[i];
    }

    lv_activity_ext_t * ext = activity_get_ext();
    lv_obj_t * tileview = ext->tileview;

    if(NULL == ext->tile_distribution_cont) {
        ext->tile_distribution_cont = activity_tileview_add_tile(tileview, id);
    } else {
        if((0 == memcmp(s_active, active, ACTIVITY_OCLOCK_CNT)) && (tm_hour == ext->rtc_time.tm_hour)) {
            return;
        }
        memcpy(s_active, active, ACTIVITY_OCLOCK_CNT);
        tm_hour = ext->rtc_time.tm_hour;

        lv_obj_clean(ext->tile_distribution_cont);
    }
    lv_obj_t * cont = ext->tile_distribution_cont;
    lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(cont);

    //title
    lv_obj_t * title = lv_label_create(cont, NULL);
    lv_label_set_text_id(title, WATCH_TEXT_ID_ACTIVITY_DISTRIBUTION);
    lv_obj_add_style(title, LV_LABEL_PART_MAIN, &lv_watch_font20_gray);
    lv_obj_align(title, NULL, LV_ALIGN_IN_TOP_MID, 0, 10*LV_VER_RES/240);
    lv_obj_set_base_dir(title, bidi_dir);

    //x axis line
    static lv_point_t x_axis_line_points[2];
    static lv_point_t y_axis_line_points[ACTIVITY_OCLOCK_CNT][2];

    lv_coord_t x_begin;
    if(LV_BIDI_DIR_RTL == bidi_dir) {
        x_begin = 220*LV_HOR_RES/240;
    } else {
        x_begin = 20*LV_HOR_RES/240;
    }
    lv_coord_t x_end = LV_HOR_RES - x_begin;
    lv_coord_t x_interval = (x_end - x_begin) / (ACTIVITY_OCLOCK_CNT - 1);
    lv_coord_t y_begin = LV_VER_RES *7/12;
    lv_coord_t y_end = LV_VER_RES /4;

    lv_obj_t * line = lv_line_create(cont, NULL);
    lv_obj_set_style_local_line_color(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
    lv_obj_set_style_local_line_width(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 2);
    lv_obj_set_style_local_line_opa(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50);

    x_axis_line_points[0].x = x_begin;
    x_axis_line_points[0].y = y_begin;
    x_axis_line_points[1].x = x_end;
    x_axis_line_points[1].y = y_begin;
    lv_line_set_points(line, x_axis_line_points, 2);
    lv_obj_set_x(line, 0);

    //y axis line
    for(uint8_t i=0; i<ACTIVITY_OCLOCK_CNT; i++) {
        if(ext->rtc_time.tm_hour < (i + 7)) { //from 7 o'clock till now
            break;
        }

        y_axis_line_points[i][0].x = x_begin + x_interval * i;
        y_axis_line_points[i][0].y = y_begin;
        y_axis_line_points[i][1].x = x_begin + x_interval * i;
        y_axis_line_points[i][1].y = y_end;

        line = lv_line_create(cont, NULL);
        lv_line_set_points(line, y_axis_line_points[i], 2);
        lv_obj_set_style_local_line_width(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 10*LV_HOR_RES/240);
        lv_obj_set_style_local_line_opa(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);

        if(1 == active[i]) {
            lv_obj_set_style_local_line_color(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED);
            active_cnt ++;
        } else {
            lv_obj_set_style_local_line_color(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
            inactive_cnt ++;
        }
        lv_obj_set_x(line, 0);
    }

    if(active_cnt + inactive_cnt > 0) {
        active_percent = 100 * active_cnt / (active_cnt + inactive_cnt);
        inactive_percent = 100 - active_percent;
    }

    //label hours
    const char * text[ACTIVITY_OCLOCK_TEXT_CNT] = {"7:00", "12:00", "17:00", "22:00"};
    lv_coord_t text_x;
    lv_obj_t * label;
    for(uint8_t i=0; i<ACTIVITY_OCLOCK_TEXT_CNT; i++) {
        label = lv_label_create(cont, NULL);
        if(LV_BIDI_DIR_RTL == bidi_dir) {
            lv_obj_set_base_dir(label, LV_BIDI_DIR_LTR);
        }
        lv_obj_set_style_local_text_font(label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_THEME_WATCH_NIGHT_FONT_14);
        lv_label_set_text(label, text[i]);
        text_x = x_begin + x_interval * i * 5 - lv_obj_get_width(label) / 2;
        lv_obj_set_pos(label, text_x, y_begin);
    }

    //btn inactive
    lv_obj_t * btn_inactive = lv_btn_create(cont, NULL);
    lv_obj_add_style(btn_inactive, LV_BTN_PART_MAIN, &lv_style_transp_fit);
    lv_btn_set_fit2(btn_inactive, LV_FIT_TIGHT, LV_FIT_NONE);
    lv_btn_set_layout(btn_inactive, LV_LAYOUT_ROW_MID);
    lv_obj_set_click(btn_inactive, false);
    lv_obj_set_base_dir(btn_inactive, bidi_dir);

    lv_obj_t * cont_inactive = lv_cont_create(btn_inactive, NULL);
    lv_obj_set_size(cont_inactive, 20, 20);
    lv_obj_set_style_local_bg_color(cont_inactive, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
    lv_obj_set_style_local_bg_opa(cont_inactive, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
    lv_obj_set_style_local_radius(cont_inactive, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, 100);
    lv_obj_set_style_local_border_width(cont_inactive, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, 0);

    lv_obj_t * label_inactive = lv_label_create(btn_inactive, NULL);
    lv_label_set_text_id(label_inactive, WATCH_TEXT_ID_INACTIVE);

    lv_obj_t * label_inactive_percent = lv_label_create(btn_inactive, NULL);
    char str[ACTIVITY_STR_LENGTH];
    memset(str, 0, ACTIVITY_STR_LENGTH);
    snprintf(str, ACTIVITY_STR_LENGTH, "%d%%", inactive_percent);
    lv_label_set_text(label_inactive_percent, str);

    lv_obj_align(btn_inactive, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -10*LV_VER_RES/240);

    //btn active
    lv_obj_t * btn_active = lv_btn_create(cont, btn_inactive);
    lv_obj_align(btn_active, btn_inactive, LV_ALIGN_OUT_TOP_LEFT, 0, -4*LV_VER_RES/240);

    lv_obj_t * cont_active = lv_cont_create(btn_active, cont_inactive);
    lv_obj_set_style_local_bg_color(cont_active, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED);

    lv_obj_t * label_active = lv_label_create(btn_active, label_inactive);
    lv_label_set_text_id(label_active, WATCH_TEXT_ID_ACTIVE);

    lv_obj_t * label_active_percent = lv_label_create(btn_active, label_inactive_percent);
    memset(str, 0, ACTIVITY_STR_LENGTH);
    snprintf(str, ACTIVITY_STR_LENGTH, "%d%%", active_percent);
    lv_label_set_text(label_active_percent, str);
}

static void tile_steps_create(uint8_t id)
{
    uint32_t value_goal = activity_info.steps_goal;
    uint32_t value_today = activity_info.steps_today;
    uint32_t value_sum = 0;
    static uint32_t steps = 0;

    lv_activity_ext_t * ext = activity_get_ext();

    if(NULL == ext->tile_steps_cont) {
        ext->tile_steps_cont = activity_tileview_add_tile(ext->tileview, id);
    } else {
        if(steps == value_today) {
            return;
        }
        steps = value_today;
        lv_obj_clean(ext->tile_steps_cont);
    }

    //tile common create
    tile_common_desc_t * desc = &ext->tile_desc[0];
    Hal_Mem_Set(desc, 0, sizeof(tile_common_desc_t));
    desc->title_txt_id = WATCH_TEXT_ID_STEP_NUMBER;
    desc->title_img_src = ICON_ACTIVITY_STEPS;
    desc->value_goal = value_goal;
    desc->value_today = value_today;
    desc->value_line_color = LV_COLOR_YELLOW;

    for(uint8_t i = 0; i < ACTIVITY_WDAY_CNT; i++) {
        desc->value_wday[i] = activity_info.steps_wday[i];

        if(ext->rtc_time.tm_wday == i) {
            value_sum += desc->value_today;
        } else if (ext->rtc_time.tm_wday > i) {
            value_sum += desc->value_wday[i];
        }
    }

    uint16_t txt_id = WATCH_TEXT_ID_ACT_STEPS;
    if(desc->value_today > 1) {
        txt_id = WATCH_TEXT_ID_ACT_STEPS;
    } else {
        txt_id = WATCH_TEXT_ID_ACT_STEP;
    }
    snprintf(desc->label1_txt, ACTIVITY_STR_LENGTH, "%d %s", value_today, (char *)lv_lang_get_text(txt_id));

    if(value_sum > 1) {
        txt_id = WATCH_TEXT_ID_ACT_STEPS;
    } else {
        txt_id = WATCH_TEXT_ID_ACT_STEP;
    }
    snprintf(desc->label2_txt, ACTIVITY_STR_LENGTH, "%d %s", value_sum, (char *)lv_lang_get_text(txt_id));

    tile_common_create(ext->tile_steps_cont, desc);
}

static void tile_strength_create(uint8_t id)
{
    uint32_t value_goal = activity_info.high_strength_goal;
    uint32_t value_today = activity_info.high_strength_today;
    uint32_t value_sum = 0;
    static uint32_t strength = 0;

    lv_activity_ext_t * ext = activity_get_ext();

    if(NULL == ext->tile_strength_cont) {
        ext->tile_strength_cont = activity_tileview_add_tile(ext->tileview, id);
    } else {
        if(strength == value_today) {
            return;
        }
        strength = value_today;
        lv_obj_clean(ext->tile_strength_cont);
    }

    //tile common create
    tile_common_desc_t * desc = &ext->tile_desc[1];
    Hal_Mem_Set(desc, 0, sizeof(tile_common_desc_t));
    desc->title_txt_id = WATCH_TEXT_ID_HIGH_STRENGTH;
    desc->title_img_src = ICON_ACTIVITY_STRENGTH;
    desc->value_goal = value_goal;
    desc->value_today = value_today;
    desc->value_line_color = LV_COLOR_ORANGE;

    for(uint8_t i = 0; i < ACTIVITY_WDAY_CNT; i++) {
        desc->value_wday[i] = activity_info.high_strength_wday[i];

        if(ext->rtc_time.tm_wday == i) {
            value_sum += desc->value_today;
        } else if (ext->rtc_time.tm_wday > i) {
            value_sum += desc->value_wday[i];
        }
    }

    uint16_t txt_id = WATCH_TEXT_ID_ACT_MINS;
    if(desc->value_today > 1) {
        txt_id = WATCH_TEXT_ID_ACT_MINS;
    } else {
        txt_id = WATCH_TEXT_ID_ACT_MIN;
    }
    snprintf(desc->label1_txt, ACTIVITY_STR_LENGTH, "%d %s", value_today, (char *)lv_lang_get_text(txt_id));

    if(value_sum > 1) {
        txt_id = WATCH_TEXT_ID_ACT_MINS;
    } else {
        txt_id = WATCH_TEXT_ID_ACT_MIN;
    }
    snprintf(desc->label2_txt, ACTIVITY_STR_LENGTH, "%d %s", value_sum, (char *)lv_lang_get_text(txt_id));

    tile_common_create(ext->tile_strength_cont, desc);
}

static void tile_hours_create(uint8_t id)
{
    uint32_t value_goal = activity_info.active_hours_goal;
    uint32_t value_today = activity_info.active_hours_today;
    uint32_t value_sum = 0;
    static uint32_t hours = 0;

    lv_activity_ext_t * ext = activity_get_ext();

    if(NULL == ext->tile_hours_cont) {
        ext->tile_hours_cont = activity_tileview_add_tile(ext->tileview, id);
    } else {
        if(hours == value_today) {
            return;
        }
        hours = value_today;
        lv_obj_clean(ext->tile_hours_cont);
    }

    //tile common create
    tile_common_desc_t * desc = &ext->tile_desc[2];
    Hal_Mem_Set(desc, 0, sizeof(tile_common_desc_t));
    desc->title_txt_id = WATCH_TEXT_ID_ACTIVITY_HOURS;
    desc->title_img_src = ICON_ACTIVITY_HOURS;
    desc->value_goal = value_goal;
    desc->value_today = value_today;
    desc->value_line_color = LV_COLOR_LIME;

    for(uint8_t i = 0; i < ACTIVITY_WDAY_CNT; i++) {
        desc->value_wday[i] = activity_info.active_hours_wday[i];

        if(ext->rtc_time.tm_wday == i) {
            value_sum += desc->value_today;
        } else if (ext->rtc_time.tm_wday > i) {
            value_sum += desc->value_wday[i];
        }
    }

    uint16_t txt_id = WATCH_TEXT_ID_ACT_HOURS;
    if(desc->value_today > 1) {
        txt_id = WATCH_TEXT_ID_ACT_HOURS;
    } else {
        txt_id = WATCH_TEXT_ID_ACT_HOUR;
    }
    snprintf(desc->label1_txt, ACTIVITY_STR_LENGTH, "%d %s",value_today, (char *)lv_lang_get_text(txt_id));

    if(value_sum > 1) {
        txt_id = WATCH_TEXT_ID_ACT_HOURS;
    } else {
        txt_id = WATCH_TEXT_ID_ACT_HOUR;
    }
    snprintf(desc->label2_txt, ACTIVITY_STR_LENGTH, "%d %s", value_sum, (char *)lv_lang_get_text(txt_id));

    tile_common_create(ext->tile_hours_cont, desc);
}

static void tile_common_create(lv_obj_t * cont, tile_common_desc_t * desc)
{
    lv_activity_ext_t * ext = activity_get_ext();
    lv_obj_t * tileview = ext->tileview;
    lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(cont);

    //title
    lv_obj_t * btn_title = lv_btn_create(cont, NULL);
    lv_obj_add_style(btn_title, LV_BTN_PART_MAIN, &lv_style_transp_fit);
    lv_btn_set_fit2(btn_title, LV_FIT_TIGHT, LV_FIT_NONE);
    lv_btn_set_layout(btn_title, LV_LAYOUT_ROW_MID);
    lv_obj_set_click(btn_title, false);

    lv_obj_t * img_title = lv_img_create(btn_title, NULL);
    lv_img_set_src(img_title, desc->title_img_src);

    lv_obj_t * label_title = lv_label_create(btn_title, NULL);
    lv_label_set_text_id(label_title, desc->title_txt_id);
    lv_obj_add_style(label_title, LV_LABEL_PART_MAIN, &lv_watch_font20_gray);

    lv_obj_align(btn_title, NULL, LV_ALIGN_IN_TOP_MID, 0, 10*LV_VER_RES/240);
    lv_tileview_add_element(tileview, btn_title);
    lv_watch_obj_add_element(btn_title);

    //label today
    lv_obj_t * btn_today =  lv_btn_create(cont, btn_title);
    lv_obj_t * label_today = lv_label_create(btn_today, NULL);
    lv_label_set_text_id(label_today, WATCH_TEXT_ID_TODAY);
    lv_obj_add_style(label_today, LV_LABEL_PART_MAIN, &lv_watch_font20);

    lv_obj_t * label_today_value = lv_label_create(btn_today, label_today);
    lv_label_set_text(label_today_value, desc->label1_txt);

    lv_obj_align(btn_today, btn_title, LV_ALIGN_OUT_BOTTOM_MID, 0, 10*LV_VER_RES/240);

    //x axis base line
    lv_coord_t x_begin;
    if(LV_BIDI_DIR_RTL == bidi_dir) {
        x_begin = 220*LV_HOR_RES/240;
    } else {
        x_begin = 20*LV_HOR_RES/240;
    }
    lv_coord_t x_end = LV_HOR_RES - x_begin;
    lv_coord_t x_interval = (x_end - x_begin) / (ACTIVITY_WDAY_CNT - 1);
    lv_coord_t y_base = LV_VER_RES * 2/3;
    lv_coord_t y_goal = LV_VER_RES / 2;

    lv_obj_t * line = lv_line_create(cont, NULL);
    lv_obj_set_style_local_line_color(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
    lv_obj_set_style_local_line_width(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 2);
    lv_obj_set_style_local_line_opa(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50);

    desc->base_line_points[0].x = x_begin;
    desc->base_line_points[0].y = y_base;
    desc->base_line_points[1].x = x_end;
    desc->base_line_points[1].y = y_base;;
    lv_line_set_points(line, desc->base_line_points, 2);
    lv_obj_set_x(line, 0);

    //x axis goal line
    line  = lv_line_create(cont, NULL);
    lv_obj_set_style_local_line_color(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
    lv_obj_set_style_local_line_width(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 2);
    lv_obj_set_style_local_line_opa(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50);

    desc->goal_line_points[0].x = x_begin;
    desc->goal_line_points[0].y = y_goal;
    desc->goal_line_points[1].x = x_end;
    desc->goal_line_points[1].y = y_goal;;
    lv_line_set_points(line, desc->goal_line_points, 2);
    lv_obj_set_x(line, 0);

    //y axis value line
    uint32_t value = 0;

    for(uint8_t i=0; i<ACTIVITY_WDAY_CNT; i++) {
        if(ext->rtc_time.tm_wday < i) { //from Sunday till now
            break;
        }

        if(ext->rtc_time.tm_wday == i) {
            value = desc->value_today;
        } else {
            value = desc->value_wday[i];
        }

        desc->value_line_points[i][0].x = x_begin + x_interval * i;
        desc->value_line_points[i][0].y = y_base;
        desc->value_line_points[i][1].x = x_begin + x_interval * i;
        desc->value_line_points[i][1].y = y_base - (y_base - y_goal) * value /desc->value_goal;

        line = lv_line_create(cont, NULL);
        lv_line_set_points(line, desc->value_line_points[i], 2);
        lv_obj_set_style_local_line_width(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 20*LV_HOR_RES/240);
        lv_obj_set_style_local_line_opa(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
        lv_obj_set_style_local_line_color(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, desc->value_line_color);
        lv_obj_set_x(line, 0);
    }

    //label goal
    lv_obj_t * label_goal = lv_label_create(cont, NULL);
    char str[ACTIVITY_STR_LENGTH];
    memset(str, 0, ACTIVITY_STR_LENGTH);
    snprintf(str, ACTIVITY_STR_LENGTH, "%d", desc->value_goal);
    lv_label_set_text(label_goal, str);
    lv_obj_add_style(label_goal, LV_LABEL_PART_MAIN, &lv_watch_font14);
    if(LV_BIDI_DIR_RTL == bidi_dir) {
        lv_obj_set_pos(label_goal, x_begin - lv_obj_get_width(label_goal), y_goal - 20);
    } else {
        lv_obj_set_pos(label_goal, x_begin, y_goal - 20);
    }

    //label weekday
    lv_coord_t x_text;
    lv_obj_t * label_weekday;
    for(uint8_t i=0; i<ACTIVITY_WDAY_CNT; i++) {
        label_weekday = lv_label_create(cont, NULL);
        lv_obj_add_style(label_weekday, LV_LABEL_PART_MAIN, &lv_watch_font14);
        lv_label_set_text_id(label_weekday, week_txt_id[i]);
        x_text = x_begin + x_interval * i - lv_obj_get_width(label_weekday) / 2;
        lv_obj_set_pos(label_weekday, x_text, y_base);
    }

    //label this week
    lv_obj_t * btn_this_week =  lv_btn_create(cont, btn_title);
    lv_obj_t * label_this_week = lv_label_create(btn_this_week, NULL);
    lv_label_set_text_id(label_this_week, WATCH_TEXT_ID_THIS_WEEK);
    lv_obj_add_style(label_this_week, LV_LABEL_PART_MAIN, &lv_watch_font20);

    lv_obj_t * label_this_week_value = lv_label_create(btn_this_week, label_this_week);
    lv_label_set_text(label_this_week_value, desc->label2_txt);

    lv_obj_align(btn_this_week, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -20*LV_VER_RES/240);
}

static void activity_update_anim(lv_obj_t * obj) {
    lv_anim_t a;
    lv_anim_path_t path;

    lv_anim_path_init(&path);
    lv_anim_path_set_cb(&path, lv_anim_path_step);

    lv_anim_init(&a);
    lv_anim_set_var(&a, obj);
    lv_anim_set_start_cb(&a, (lv_anim_ready_cb_t)activity_update_anim_cb);
    lv_anim_set_path(&a, &path);
    lv_anim_set_time(&a, 1);
    lv_anim_set_playback_time(&a, 0);
    lv_anim_set_playback_delay(&a, 0);
    lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
    lv_anim_set_repeat_delay(&a, 1000);

    lv_anim_start(&a);
}

static void activity_update_anim_cb(lv_anim_t * anim)
{
    if(lv_watch_get_activity_obj(ACT_ID_ACTIVITY) == NULL) {
        lv_obj_t * cont = anim->var;
        lv_obj_clean(cont);
        app_adaptor_get_activity_info_req(&activity_info);
        tile_summary_add_element(cont);
        return;
    }
    lv_activity_ext_t * ext = activity_get_ext();
    if(NULL == ext) return;

    //get activity info
    app_adaptor_get_activity_info_req(&activity_info);

    //get rtc time
    Hal_Rtc_Gettime(&ext->rtc_time);

    //get tile act
    lv_coord_t x, y;
    lv_tileview_get_tile_act(ext->tileview, &x, &y);

    //update tile
    if(y > 0) {
        tile_create_func[y-1](y-1);
    }

    tile_create_func[y](y);

    if(y + 1 < ACTIVITY_TILE_COUNT) {
        tile_create_func[y+1](y+1);
    }
}

#endif /*USE_LV_WATCH_ACTIVITY*/
